package io.gitee.twoke.generator.spring;

import io.gitee.twoke.generator.engine.GenerateEngine;
import io.gitee.twoke.generator.engine.impl.cfg.GenerateEngineConfigurationImpl;
import io.gitee.twoke.generator.engine.impl.cfg.SpringBeanFactoryProxyMap;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class GenerateEngineFactoryBean implements FactoryBean<GenerateEngine>, DisposableBean, ApplicationContextAware {

  protected GenerateEngineConfigurationImpl generateEngineConfiguration;

  protected ApplicationContext applicationContext;
  protected GenerateEngine generateEngine;

  public void destroy() throws Exception {
    if (generateEngine != null) {
      generateEngine.close();
    }
  }

  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
  }

  public GenerateEngine getObject() throws Exception {
    configureExternallyManagedTransactions();

    if (generateEngineConfiguration.getBeans() == null) {
      generateEngineConfiguration.setBeans(new SpringBeanFactoryProxyMap(applicationContext));
    }

    this.generateEngine = generateEngineConfiguration.buildGenerateEngine();
    return this.generateEngine;
  }


  protected void configureExternallyManagedTransactions() {
    if (generateEngineConfiguration instanceof SpringGenerateEngineConfiguration) { // remark: any config can be injected, so we cannot have SpringConfiguration as member
      SpringGenerateEngineConfiguration engineConfiguration = (SpringGenerateEngineConfiguration) generateEngineConfiguration;
      if (engineConfiguration.getTransactionManager() != null) {
        generateEngineConfiguration.setTransactionsExternallyManaged(true);
      }
    }
  }

  public Class<GenerateEngine> getObjectType() {
    return GenerateEngine.class;
  }

  public boolean isSingleton() {
    return true;
  }

  public GenerateEngineConfigurationImpl getGenerateEngineConfiguration() {
    return generateEngineConfiguration;
  }

  public void setGenerateEngineConfiguration(GenerateEngineConfigurationImpl generateEngineConfiguration) {
    this.generateEngineConfiguration = generateEngineConfiguration;
  }
}